Skip to content

Add managed redis config value tool and use it for scan interlock settings#959

Merged
d-perl merged 9 commits into
mainfrom
feat/better_interlock_config
Jun 17, 2026
Merged

Add managed redis config value tool and use it for scan interlock settings#959
d-perl merged 9 commits into
mainfrom
feat/better_interlock_config

Conversation

@d-perl

@d-perl d-perl commented Jun 15, 2026

Copy link
Copy Markdown
Contributor
  • Adds a RedisConfigValue which associates to a config value in Redis which can be subscribed to, and infers the type of the config value from the endpoint and message type
  • Uses this for the interlock enabled config value
  • Uses this to determine whether to restart a scan or not if the interlock triggers.

@d-perl d-perl force-pushed the feat/better_interlock_config branch 2 times, most recently from 112815d to 648dbb0 Compare June 16, 2026 07:48
@d-perl d-perl marked this pull request as ready for review June 16, 2026 07:48
@d-perl d-perl force-pushed the feat/better_interlock_config branch from 648dbb0 to b81e21c Compare June 16, 2026 08:06
@d-perl d-perl requested a review from a team June 16, 2026 08:07
@d-perl d-perl force-pushed the feat/better_interlock_config branch from b81e21c to e334fa4 Compare June 16, 2026 08:31
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

@d-perl d-perl changed the title feat: add managed redis config value tool Add managed redis config value tool and use it for scan interlock settings Jun 16, 2026
@d-perl d-perl force-pushed the feat/better_interlock_config branch from e334fa4 to 25c0b6f Compare June 16, 2026 09:08

@wyzula-jan wyzula-jan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current version crashes the bec-scan-server, I made sure to flush redis, install all packages again in env, and upon restarting server. How you were able to get it running locally during development? Am I missing some steps?

Error:

 | 2026-06-16 12:16:32 | bec_lib.bec_service | [INFO] | Connecting to Redis server at localhost:6379
ScanServer | 2026-06-16 12:16:35 | bec_lib.bec_service | [INFO] | Waiting for DeviceServer.
ScanServer | 2026-06-16 12:16:35 | bec_lib.bec_service | [SUCCESS] | DeviceServer is running.
ScanServer | 2026-06-16 12:16:35 | bec_lib.devicemanager | [WARNING] | No config available.
ScanServer | 2026-06-16 12:16:35 | bec_lib.devicemanager | [INFO] | Adding new devices:

ScanServer | 2026-06-16 12:16:35 | bec_server.scan_server.scan_queue | [INFO] | New scan queue:
ScanServer | 2026-06-16 12:16:35 | bec_server.scan_server.scan_queue | [INFO] |
              primary queue / ScanQueueStatus.RUNNING
┏━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ queue_idscan_idis_scan ┃ type ┃ scan_numberIQ status ┃
┡━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━┩
└──────────┴─────────┴─────────┴──────┴─────────────┴───────────┘

ScanServer | 2026-06-16 12:16:35 | bec_server.procedures.manager | [SUCCESS] | Initialising ProcedureManager, using worker type 'SubProcessWorker'...
ScanServer | 2026-06-16 12:16:35 | bec_server.procedures.manager | [SUCCESS] | Done initialising procedure manager.
ScanServer | 2026-06-16 12:16:35 | bec_server.procedures.manager | [SUCCESS] | Initialising ActorManager, using worker type 'ActorProcedureWorker'...
ScanServer | 2026-06-16 12:16:35 | bec_server.procedures.manager | [SUCCESS] | Done initialising procedure manager.
ScanServer | 2026-06-16 12:16:35 | bec_lib.bec_service | [INFO] | Connecting to Redis server at localhost:6379
Traceback (most recent call last):
  File "/Users/janwyzula/miniforge3/envs/bec_312/bin/bec-scan-server", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_server/bec_server/scan_server/cli/launch.py", line 21, in main
    bec_server = scan_server.ScanServer(config=config, connector_cls=RedisConnector)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_server/bec_server/scan_server/scan_server.py", line 45, in __init__
    self._start_actor_managers()
  File "/Users/janwyzula/PSI/bec/bec_server/bec_server/scan_server/scan_server.py", line 91, in _start_actor_managers
    self.builtin_actor_manager = BuiltinActorManager(self.bootstrap_server)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_server/bec_server/actors/builtin_actor_manager.py", line 48, in __init__
    self._client.start()
  File "/Users/janwyzula/PSI/bec/bec_lib/bec_lib/client.py", line 219, in start
    self.builtin_actors = BuiltinActorHli(self)
                          ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_lib/bec_lib/builtin_actor_hli.py", line 113, in __init__
    self.scan_interlock = ScanInterlockHli(self._client, self)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_lib/bec_lib/builtin_actor_hli.py", line 27, in __init__
    self._enabled = RedisConfigValue(
                    ^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_lib/bec_lib/config_values.py", line 31, in __init__
    self._config = self._fetch()
                   ^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_lib/bec_lib/config_values.py", line 42, in _fetch
    existing = self._connector.xread(self._ep, id="+", count=1)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_lib/bec_lib/redis_connector.py", line 184, in wrapper
    return func(*tuple(arg), **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/PSI/bec/bec_lib/bec_lib/redis_connector.py", line 1476, in xread
    msg = client.xread({topic: id}, count=count, block=block)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/commands/core.py", line 4001, in xread
    return self.execute_command("XREAD", *pieces, keys=keys)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/client.py", line 621, in execute_command
    return self._execute_command(*args, **options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/client.py", line 632, in _execute_command
    return conn.retry.call_with_retry(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/retry.py", line 105, in call_with_retry
    return do()
           ^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/client.py", line 633, in <lambda>
    lambda: self._send_command_parse_response(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/client.py", line 604, in _send_command_parse_response
    return self.parse_response(conn, command_name, **options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/client.py", line 651, in parse_response
    response = connection.read_response()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/janwyzula/miniforge3/envs/bec_312/lib/python3.12/site-packages/redis/connection.py", line 672, in read_response
    raise response
redis.exceptions.ResponseError: Invalid stream ID specified as stream command argument

States and interlock on main before switching branches:

default@bec [1/1] ❯❯ bec.builtin_actors.scan_interlock.states_watched
Out[1]: {}

• default@bec [2/1] ❯❯ bec.builtin_actors.scan_interlock.enabled
Out[2]: Falsedefault@bec [3/1] ❯❯ bec.beamline_states.show_all()
               Beamline States
┏━━━━━━┳━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┓
┃ NameTypeParametersStatusLabel ┃
┃      ┃      ┃            ┃        ┃       ┃
┡━━━━━━╇━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━┩
└──────┴──────┴────────────┴────────┴───────┘

• default@bec [4/1] ❯❯

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a typed, subscribable Redis-backed configuration abstraction (RedisConfigValue) and migrates scan interlock enablement + interlock-trigger behavior (restart/pause/do-nothing) to use it, including updates to server-side actor management and client HLI.

Changes:

  • Added ManagedConfigMessage message pattern plus new scan-interlock config messages/endpoints.
  • Implemented RedisConfigValue to read/write STREAM-based config values and notify subscribers.
  • Updated scan interlock actor + builtin actor manager + HLI and expanded unit/e2e test coverage around the new config-driven behavior.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
bec_server/tests/tests_scan_server/test_builtin_actor_manager.py Updates tests for builtin actor manager behavior after moving to config-value-driven enablement and new handler names.
bec_server/bec_server/actors/scan_interlock.py Uses a Redis-managed config value to decide whether to restart (or pause) scans when the interlock triggers.
bec_server/bec_server/actors/builtin_actor_manager.py Switches scan interlock lifecycle management to a Redis-managed enabled flag and renames the beamline-state handler.
bec_lib/tests/test_managed_config_values.py Adds unit tests validating RedisConfigValue behavior and type constraints.
bec_lib/bec_lib/tests/utils.py Adds a wait_until helper used by the new managed-config tests.
bec_lib/bec_lib/redis_connector.py Minor readability fix in stream subscription tracking (topic not in ...).
bec_lib/bec_lib/messages.py Introduces ManagedConfigMessage, BoolConfigDefaultFalse, and scan-interlock trigger setting enum/message.
bec_lib/bec_lib/endpoints.py Adds scan interlock config endpoints and adjusts typing of endpoint message type var.
bec_lib/bec_lib/config_values.py New RedisConfigValue implementation (Redis-backed, subscribable config value).
bec_lib/bec_lib/client.py Moves builtin_actors initialization into start() so the connector is available.
bec_lib/bec_lib/builtin_actor_hli.py Migrates scan interlock HLI to read/write Redis-managed enable + trigger-setting config values.
bec_ipython_client/tests/end-2-end/test_actors_e2e.py Extends e2e actor test to set/verify scan interlock trigger setting via the HLI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread bec_lib/bec_lib/config_values.py Outdated
Comment thread bec_lib/bec_lib/config_values.py Outdated
Comment thread bec_server/bec_server/actors/builtin_actor_manager.py Outdated
Comment thread bec_lib/tests/test_managed_config_values.py Outdated
Comment thread bec_lib/bec_lib/tests/utils.py
Comment thread bec_server/bec_server/actors/builtin_actor_manager.py
@d-perl

d-perl commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

The current version crashes the bec-scan-server, I made sure to flush redis, install all packages again in env, and upon restarting server. How you were able to get it running locally during development? Am I missing some steps?

pretty weird, it works on my machine both at work and home, as well as with redis in CI. it should work without flushing redis or any of that. maybe some weird redis for macos issue? anyway, I changed one of the lines that looked like it could be responsible, would you try again?

@d-perl d-perl requested a review from wyzula-jan June 16, 2026 12:02

@wyzula-jan wyzula-jan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First part, some minor comments to the code, but I noticed bug when ScanInterlock forgets the trigger settings -> showed online

Comment thread bec_server/bec_server/actors/builtin_actor_manager.py
Comment thread bec_lib/bec_lib/builtin_actor_hli.py
Comment thread bec_lib/bec_lib/endpoints.py Outdated
Comment thread bec_server/tests/tests_scan_server/test_builtin_actor_manager.py Outdated
Comment thread bec_lib/bec_lib/endpoints.py Outdated

@wyzula-jan wyzula-jan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another minor finding

Comment thread bec_lib/bec_lib/config_values.py Outdated
@d-perl d-perl force-pushed the feat/better_interlock_config branch 4 times, most recently from 0cb8821 to cc114e0 Compare June 16, 2026 14:11
@d-perl d-perl force-pushed the feat/better_interlock_config branch from 3f0079c to 6c36ebb Compare June 17, 2026 07:53
@d-perl d-perl enabled auto-merge (rebase) June 17, 2026 07:59
@wyzula-jan wyzula-jan self-requested a review June 17, 2026 07:59
@d-perl d-perl merged commit 17bf8e8 into main Jun 17, 2026
36 checks passed
@d-perl d-perl deleted the feat/better_interlock_config branch June 17, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants